package Servlet;

import Dao.ArticleDAO;
import Dao.Impl.ArticleDAOImpl;
import Dto.ArticleDTO;
import Dto.CommentDto;
import Service.ArticleService;
import Service.CommentService;
import Service.UserService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mysql.cj.xdevapi.JsonArray;
import entity.Article;
import entity.Comment;
import entity.User;
import exception.BusinessException;
import org.json.JSONArray;
import org.json.JSONObject;
import req.KnowledgeBaseRequest;
import utils.DBUtil;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;
import java.util.List;

/**
 * @Author Su
 * @Date 2025/5/2 22:42
 * @Version 1.0 （版本号）
 */
@WebServlet("/api/comment/")
public class CommentServlet extends HttpServlet {

    //成员变量，Servlet的依赖组件
    private ArticleDAO articleDAO;
    private CommentService commentService;
    private ObjectMapper objectMapper;
    private Connection connection;//连接池

    @Override

    //int Servlet首次加载时自动执行一次，用于初始化资源（如数据库连接、配置等
    public void init() throws ServletException {
        try {

            //todo：数据库连接好像不能这样写，不管了，，，
            //每次重启Servlet都会创建新连接，高并发会很耗资源，而且没在destroy()中关闭连接，一样，可能数据库连接数累积直至崩溃
            //********连接池
            connection = DBUtil.getConnection();


           // 初始化DAO和服务对象
            this.articleDAO = new ArticleDAOImpl(connection);//文章数据访问对象（直接操作数据库，如增删改查文章）
            this.objectMapper = new ObjectMapper();
            this.commentService = new CommentService(connection);//评论业务逻辑层，权限校验啥的

            //？？？硬编码初始化	难以维护和扩展	使用Spring等框架依赖注入
        } catch (SQLException e) {
            throw new ServletException("初始化数据库连接失败", e);
        }
    }

    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("application/json;charset=UTF-8");
        resp.setCharacterEncoding("UTF-8");

        //初始化数据库连接与JSON响应

        // 构造JSON响应
        JSONObject responseJson = new JSONObject();
        try {
            connection = DBUtil.getConnection();
        } catch (SQLException throwables) {
            throwables.printStackTrace();// 连接失败仅打印日志，不终止流程
        }
        try {
            HttpSession session = req.getSession(false);
            if (session == null) {
                responseJson.put("code", 401);
                responseJson.put("message", "未登录");
                resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                return;
            }

            User user = (User) req.getSession().getAttribute("user");

            //解析请求体

            // 将请求体中的JSON数据解析为Comment对象
            Comment commentReq = objectMapper.readValue(req.getReader(), Comment.class);
            // 设置评论用户ID
            commentReq.setUserId(user.getUserId());

            // 检查文章是否存在。用dto，bu用entity，dto可以只封装需要的字段，安全一点，entityarticle可能包含作者密码这些，参考springboot
            ArticleDTO article = articleDAO.getArticleById(commentReq.getArticleId());
            if (article == null) {
                responseJson.put("code", 200);
                responseJson.put("message", "评论的文章不存在");
                return;
            }

            // 处理父评论
            if (commentReq.getParentId() != null) {
                CommentDto comment = commentService.getCommentById(commentReq.getParentId());
                commentReq.setRootId(comment.getRootId()); // 设置根评论ID（保持评论层级）
            }//确保回复的评论属于同一话题链


            // 插入评论
            commentService.addComment(commentReq);// 调用服务层插入评论
            responseJson.put("code", 200);
            responseJson.put("message", "添加成功");

        } catch (BusinessException e) {// 自定义业务异常
            responseJson.put("code", 403);
            responseJson.put("message", e.getMessage());
            resp.setStatus(HttpServletResponse.SC_FORBIDDEN);
        } catch (SQLException e) {
            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        } finally {
            // 输出JSON响应
            resp.getWriter().print(responseJson.toString());
            // 释放数据库连接
            DBUtil.closeConnection(connection);
        }
    }

    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        req.setCharacterEncoding("UTF-8");
        resp.setContentType("application/json;charset=UTF-8");
        resp.setCharacterEncoding("UTF-8");
        JSONObject responseJson = new JSONObject();
        try {
            connection = DBUtil.getConnection();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        try {
            HttpSession session = req.getSession(false);
            if (session == null) {
                responseJson.put("code", 401);
                responseJson.put("message", "未登录");
                resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                return;
            }

            User user = (User) req.getSession().getAttribute("user");

            //解析请求体
            String articleId = req.getParameter("articleId");
            if(articleId == null){
                throw new BusinessException("缺乏参数");
            }
            CommentDto commentReq = new CommentDto();
            // 设置文章ID到DTO
            commentReq.setArticleId(Integer.parseInt(articleId));

            // **处理根评论ID
            if(req.getParameter("rootId") != null){
                commentReq.setRootId(Integer.parseInt(req.getParameter("rootId")));
            }
            // -----查找文章所有评论
            // 调用服务层查询评论列表
            List<Comment> comments = commentService.selectComment(commentReq);
            responseJson.put("code",200);
            responseJson.put("message","执行成功");
            responseJson.put("data",new JSONArray(objectMapper.writeValueAsString(comments)));

        } catch (BusinessException e) {
            responseJson.put("code", 403);
            responseJson.put("message", e.getMessage());
            resp.setStatus(HttpServletResponse.SC_FORBIDDEN);
        } catch (SQLException e) {
            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        } finally {
            resp.getWriter().print(responseJson.toString());
        }
    }
}
